package com.spring.framework.config.async.annotation;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

/**
 * 异步方法支持三种返回值类型（排除void），这个源码在AsyncExecutionAspectSupport的doSubmit方法中：
 * <p>
 * 1. CompletableFuture：首先判断如果返回值类型是CompletableFuture及其子类，那么最终会默认返回一个Spring为我们创建的CompletableFuture对象；
 * <p>
 * 2. ListenableFuture：其次判断如果返回值类型是ListenableFuture及其子类，那么最终会默认返回一个Spring为我们创建的ListenableFutureTask对象；
 * <p>
 * 3. Future：随后判断如果异步方法返回值类型是Future及其子类，那么最终会默认返回一个Spring为我们创建的FutureTask对象；
 * <p>
 * 4. 最后，如果以上判断都不满足，即如果异步方法指定了返回其它类型，那么最终将返回一个null。正常返回时，返回的结果对象和我们在方法中返回的对象也不是同一个。
 * <p>
 * 具有返回值的异步方法执行过程中产生的异常会被封装到Future中，因此很方法方便处理，它的get()方法就能抛出在执行过程中捕获的异常，而对于高级的Future，
 * 比如CompletableFuture和ListenableFuture则可以注册异常处理函数。
 * <p>
 * 对于无返回值的异步方法，异常不能被封装，也不会被直接抛出，而是需要通过异常处理器处理，默认异常处理器是SimpleAsyncUncaughtExceptionHandler，它的
 * 逻辑是直接在调用对应方法的线程中通过error级别日志打印这个异常信息（不是抛出异常）。可以自定义一个异常处理器来处理抛出的异常，做出各种业务逻辑：对于
 * Java配置，可以通过重写AsyncConfigurer的getAsyncUncaughtExceptionHandler方法返回一个AsyncUncaughtExceptionHandler异常处理器；对于XML配置可
 * 以设置< task:annotation-driven/>标签的exception-handler属性指向一个异常处理器bean定义。
 *
 * @author xuweizhi
 * @since 2021/07/09 16:18
 */
@Component
public class FutureTaskMethod {

	/**
	 * 返回Future
	 */
	@Async
	public Future<Integer> future(int i) throws InterruptedException {
		System.out.println("-----执行future方法的线程：" + Thread.currentThread().getName());
		Thread.sleep(2000);
		ListenableFuture<Integer> integerListenableFuture = AsyncResult.forValue(i);
		System.out.println("方法中的Future :" + integerListenableFuture);
		return integerListenableFuture;
	}

	/**
	 * 返回CompletableFuture
	 */
	@Async
	public CompletableFuture<Integer> completableFuture(int i) throws InterruptedException {
		System.out.println("-----执行completableFuture方法的线程：" + Thread.currentThread().getName());
		Thread.sleep(2000);
		CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.completedFuture(i);
		System.out.println("方法中的CompletableFuture :" + integerCompletableFuture);
		//int j=1/0;
		return integerCompletableFuture;
	}

	/**
	 * 返回ListenableFuture
	 */
	@Async
	public ListenableFuture<Integer> listenableFuture(int i) throws InterruptedException {
		System.out.println("-----执行listenableFuture方法的线程：" + Thread.currentThread().getName());
		Thread.sleep(2000);
		ListenableFuture<Integer> integerListenableFuture = AsyncResult.forValue(i);
		System.out.println("方法中的ListenableFuture :" + integerListenableFuture);
		return integerListenableFuture;
	}

	/**
	 * 无返回 {@link MyAsyncConfigurer#getAsyncUncaughtExceptionHandler()}
	 */
	@Async
	public void noReturn(int i) throws InterruptedException {
		System.out.println("-----noReturn：" + Thread.currentThread().getName());
		Thread.sleep(3000);
		//制造一个异常
		int j = 1 / 0;
	}

}
